/*
 * FanController.cpp
 *
 *  Created on: Jul 26, 2013
 *      Author: User
 */

#include "FanController.h"

FanControl Fan1;

static int rpmCount = 0;

void rpm_fan() {

	rpmCount++;

}

void FanControl::initialize(int pinTACH, int pinCNTL) {

	this->pinCNTL = pinCNTL;
	this->pinTACH = pinTACH;

	Timer1.initialize();
	Timer1.pwm(pinCNTL, 800, 40);

	pinMode(pinTACH, INPUT);     //set the pin to input
    digitalWrite(pinTACH, HIGH); //use the internal pullup resistor

    PCintPort::attachInterrupt(pinTACH, rpm_fan, RISING);

    huntMaxSpeed(10);
    huntMinSpeed(10);

}

int FanControl::getRPM() {

	cli(); 						// Disable interrupts
	rpmCount = 0;				// Reset count

	sei(); 						// Enable interrupts
	delay (1000); 				// Sample for 1 second
	return rpmCount * 30; 		// Each rotation counts twice.  Formula is ( count * 60 / 2 )

}

int FanControl::huntMaxSpeed(int slop) {

	int curReading = 1, prevReading = 9999;

	setPWMValue(800); //80% duty cycle in linear range

	while (abs(curReading - prevReading) > slop) {
		prevReading = curReading;
		curReading = getRPM();
	}

	this->maxSpeed = curReading;
	return curReading;

}

int FanControl::huntMinSpeed(int slop) {

	int curReading = 1, prevReading = 9999;

	setPWMValue(400); //40% duty cycle in linear range

	while (abs(curReading - prevReading) > slop) {
		prevReading = curReading;
		curReading = getRPM();
	}

	this->minSpeed = curReading;
	return curReading;

}

void FanControl::setPWMValue(int newValue) {

	Timer1.setPwmDuty(pinCNTL, newValue % 1024);

}

void FanControl::setRPMValue(int newValue, int withinPercent, int numTries) {

	if (newValue > maxSpeed) setPWMValue(800);
	else if  (newValue < minSpeed) setPWMValue(400);
	else setPWMValue(map(newValue, minSpeed, maxSpeed, 400, 800));

}
